//=============================================================================
// Taskforces - coded and designed by Johannes Sievert aka [A|K]Leviathan
//=============================================================================
class TFGame extends xTeamGame;

var cache string  MapPrefixtwo;  // Prefix characters for names of maps for this game type.
var config int	BountyAmount;
var config int	OutpostDist;
var config int	StartupResources;
var config int	BuildLimit;
var config int	OutpostArea;
var config int	GeneratorRate;
var config bool	BuildAreas;
var config int	MinimumIncome;
var config int  SkillAmount;
var config bool ToggleWarhead;
var config bool FastBuildTime;
var config bool Terr;
var config int  MaxSentinel;
var config bool AllowUpgrades;
var config bool UnlimitedRES;

const SIGPROPNUM = 15;
var localized string SIGPropsDisplayText[SIGPROPNUM];
var localized string SIGPropDescText[SIGPROPNUM];

var() class<weapon> DefWeapons[4];

static function FillPlayInfo(PlayInfo PlayInfo)
{
	local int i;

	Super.FillPlayInfo(PlayInfo);  // Always begin with calling parent

	PlayInfo.AddSetting(default.GameGroup, "BountyAmount", default.SIGPropsDisplayText[i++], 40, 1, "Text", "5;0:99999");
	PlayInfo.AddSetting(default.GameGroup, "OutpostDist", default.SIGPropsDisplayText[i++], 40, 1, "Text", "5;0:99999");
	PlayInfo.AddSetting(default.GameGroup, "StartupResources", default.SIGPropsDisplayText[i++], 40, 1, "Text", "5;0:3000");
	PlayInfo.AddSetting(default.GameGroup, "BuildLimit", default.SIGPropsDisplayText[i++], 40, 1, "Text", "5;0:99999");
	PlayInfo.AddSetting(default.GameGroup, "OutpostArea", default.SIGPropsDisplayText[i++], 40, 1, "Text", "5;0:99999");
	PlayInfo.AddSetting(default.GameGroup, "GeneratorRate", default.SIGPropsDisplayText[i++], 40, 1, "Text", "5;0:99999");
    PlayInfo.AddSetting(default.GameGroup, "BuildAreas",    default.SIGPropsDisplayText[i++], 0,  1, "Check",        ,,     , false);
    PlayInfo.AddSetting(default.GameGroup, "MinimumIncome", default.SIGPropsDisplayText[i++], 40, 1, "Text", "5;0:99999");
	PlayInfo.AddSetting(default.GameGroup, "SkillAmount", default.SIGPropsDisplayText[i++], 40, 1, "Text", "5;0:99999");
    PlayInfo.AddSetting(default.GameGroup, "ToggleWarhead", default.SIGPropsDisplayText[i++], 0,  1, "Check",        ,,     , false);
	PlayInfo.AddSetting(default.GameGroup, "FastBuildTime", default.SIGPropsDisplayText[i++], 0,  1, "Check",        ,,     , true);
	PlayInfo.AddSetting(default.GameGroup, "Terr", default.SIGPropsDisplayText[i++], 0,  1, "Check",        ,,     , false);
	PlayInfo.AddSetting(default.GameGroup, "MaxSentinel", default.SIGPropsDisplayText[i++], 40, 1, "Text", "5;0:20");
	PlayInfo.AddSetting(default.GameGroup, "AllowUpgrades", default.SIGPropsDisplayText[i++], 0,  1, "Check",        ,,     , false);
	PlayInfo.AddSetting(default.GameGroup, "UnlimitedRES", default.SIGPropsDisplayText[i++], 0,  1, "Check",        ,,     , true);
}

static event string GetDescriptionText(string PropName)
{
	switch (PropName)
	{
		case "BountyAmount":	return default.SIGPropDescText[0];
		case "OutpostDist":	return default.SIGPropDescText[1];
		case "StartupResources":	return default.SIGPropDescText[2];
		case "BuildLimit":	return default.SIGPropDescText[3];
		case "OutpostArea":	return default.SIGPropDescText[4];
		case "GeneratorRate":	return default.SIGPropDescText[5];
        case "BuildAreas":	return default.SIGPropDescText[6];
        case "MinimumIncome":	return default.SIGPropDescText[7];
		case "SkillAmount":	return default.SIGPropDescText[8];
		case "ToggleWarhead": return default.SIGPropDescText[9];
		case "FastBuildTime": return default.SIGPropDescText[10];
		case "Terr": return default.SIGPropDescText[11];
		case "MaxSentinel": return default.SIGPropDescText[12];
		case "AllowUpgrades": return default.SIGPropDescText[13];
		case "UnlimitedRES": return default.SIGPropDescText[14];
	}

	return Super.GetDescriptionText(PropName);
}

function AddDefaultInventory( pawn PlayerPawn )
{
    local Weapon newWeapon;
	local int i;

	for(i=0;i<3;i++)
	{
    	if( (DefWeapons[i]!=None) && (PlayerPawn.FindInventoryType(DefWeapons[i])==None) )
    	{
    	    newWeapon = Spawn(DefWeapons[i],,,PlayerPawn.Location);
   	 	    if( newWeapon != none )
    	    {
   		        newWeapon.GiveTo(PlayerPawn);
    	        newWeapon.bCanThrow = false;
      	  	}
  		}
	}

    SetPlayerDefaults(PlayerPawn);

    //reset players stats
	if(tfpri(playerpawn.Controller.PlayerReplicationInfo)!=none)
	{
	    tfpri(playerpawn.Controller.PlayerReplicationInfo).resetabilities();

        tfpri(playerpawn.Controller.PlayerReplicationInfo).credits+=
            tfgri(level.game.gamereplicationinfo).teamcredits[playerpawn.Controller.PlayerReplicationInfo.team.teamindex];
    }
}

function prebeginplay()
{
    class'xGame.xBot'.default.PlayerReplicationInfoClass = class'TaskForces.TFPRI';

    Class'xGame.xPlayer'.default.PlayerReplicationInfoClass = class'TaskForces.TFPRI';
    class'xGame.xPlayer'.default.ComboNameList[0]="TaskForces.ComboPower";
    Class'xGame.xPlayer'.default.ComboNameList[1]="TaskForces.ComboDurability";
    Class'xGame.xPlayer'.default.ComboNameList[2]="TaskForces.ComboAgility";
    Class'xGame.xPlayer'.default.ComboNameList[3]="TaskForces.ComboBoost";
    gamereplicationinfoclass=class'TaskForces.TFGRI';

    super.prebeginplay();
}

simulated function postbeginplay()
{
    local actor a;

    foreach allactors( class'actor', a)
	{
	    if(xPickupBase(a)!=none)
	    {
	        xPickupBase(a).bHidden=true;
	        xPickupBase(a).Destroy();
	    }
        else if(xRealCTFBase(a)!=none)
	    {
            xRealCTFBase(a).myflag.destroy();
	        xRealCTFBase(a).bHidden=true;
	        xRealCTFBase(a).Destroy();
	    }
    }

    super.postbeginplay();
}

event Supersuper( string Options, out string Error )
{
    super.InitGame(options, error);
}

event InitGame( string Options, out string Error )
{
    super.InitGame(options, error);

    //Addmutator("TaskForces.TFMainMut",true);

    /*BountyAmount = int(ParseOption ( Options, "Bounty" ));
	OutpostDist = int(ParseOption ( Options, "OutpostDist" ));
    StartupResources = int(ParseOption ( Options, "StartupResources" ));
	BuildLimit = int(ParseOption ( Options, "BuildLimit" ));
    BuildAreas = bool(ParseOption ( Options, "BuildAreas" ));
	SkillAmount = int(ParseOption ( Options, "Skill" ));
	ToggleWarhead = bool(ParseOption ( Options, "ToggleWarhead" ));
	FastBuildTime = bool(ParseOption ( Options, "FastBuildTime" ));
	Terr = bool(ParseOption ( Options, "Terr"));
    MaxSentinel = int(ParseOption ( Options, "MaxSentinel"));
    AllowUpgrades = bool(ParseOption ( Options, "AllowUpgrades"));
    UnlimitedRES = bool(ParseOption ( Options, "UnlimitedRES"));

	Log("Collected BountyAmount: "$BountyAmount);
	Log("Collected OutpostDist: "$OutpostDist);
	Log("Collected StartupResources: "$StartupResources);
	Log("Collected ControlCapacity: "$BuildLimit);
	Log("Collected BuildAreas: "$BuildAreas);
	Log("Collected SkillAmount: "$SkillAmount);
	Log("Collected ToggleWarhead: "$ToggleWarhead);
	Log("Collected FastBuildTime: "$FastBuildTime);
    Log("Collected Terr: "$Terr);
    Log("Collected Terr: "$MaxSentinel);
    Log("Collected AllowUpgrades: "$AllowUpgrades);
    log("Collected UnlimitedRES: "$UnlimitedRES);*/
}

function bool GiveWeaponTo(string aClassName, pawn Playerpawn)
{
    local class<Weapon> WeaponClass;
	local Weapon NewWeapon;

	WeaponClass = class<Weapon>(DynamicLoadObject(aClassName, class'Class'));

	if( playerpawn.FindInventoryType(WeaponClass) != none )
		return false;
	newWeapon = playerpawn.Spawn(WeaponClass);
	if( newWeapon != none )
	{
		newWeapon.GiveTo(playerpawn);
	        return true;
    }
}

//Damage on players only - no damage management for stations here
function int ReduceDamage( int Damage, pawn injured, pawn instigatedBy, vector HitLocation, vector Momentum, class<DamageType> DamageType )
{
    local int td, ta;
    local tfpri pri;
    local float tmp, factor;

    factor=1;

    ta=7;
    td=7;

    if(injured!=none && injured.PlayerReplicationInfo!=none)
    {
        td=injured.PlayerReplicationInfo.Team.TeamIndex;
        pri=tfpri(injured.playerreplicationinfo);
    }

    if(instigatedby!=none && injured!=instigatedby && instigatedBy.PlayerReplicationInfo!=none && DamageType!=class'TaskForces.DamTypeGenFlash') ta=instigatedBy.PlayerReplicationInfo.Team.TeamIndex;

    if(((DamageType==class'TaskForces.DamTypeProtR' || DamageType==class'TaskForces.DamTypeGuardProjR') && td==0) || ((DamageType==class'TaskForces.DamTypeProtB' || DamageType==class'TaskForces.DamTypeGuardProjB') && td==1))
       return 0;

    //Spawnprotection - Damage=0
    if(pri.spawnprotected) return 0;

    //Durability
	if(pri!=none) factor/=pri.calcFactor(1);

    //Power
    if(instigatedby!=none) pri=tfpri(instigatedBy.playerreplicationinfo);
    if(pri!=none) factor*=pri.calcFactor(0);

    //Teamdamage
    if(td==ta) factor*=friendlyfirescale;

    tmp=damage*factor;
    damage*=factor;
    tmp-=damage;
    if(tmp<1 && frand()<tmp) tmp=1;
        damage+=tmp;

	return damage;
}

function Killed( Controller Killer, Controller Killed, Pawn KilledPawn, class<DamageType> damageType )
{
    local tfpri pri;
    local bool bEnemyKill;

    //Hook for Guardian/Protector-Kills
    pri=tfpri(killed.playerreplicationinfo);

    if(DamageType==class'TaskForces.DamTypeGuardProjR' || DamageType==class'TaskForces.DamTypeProtR')
    {
        killer=none;
        if(killed.playerreplicationinfo.Team.TeamIndex==0)
            tfgri(gamereplicationinfo).AddTeamRes(-BountyAmount, 0, false);
        else
            tfgri(gamereplicationinfo).AddTeamRes(BountyAmount, 0, false);
    }
    else if(DamageType==class'TaskForces.DamTypeGuardProjB' || DamageType==class'TaskForces.DamTypeProtB')
    {
        killer=none;
        if(killed.playerreplicationinfo.Team.TeamIndex==1)
            tfgri(gamereplicationinfo).AddTeamRes(-BountyAmount, 1, false);
        else
            tfgri(gamereplicationinfo).AddTeamRes(BountyAmount, 1, false);
    }

    //Killed function of Deathmatch

	bEnemyKill = ( !bTeamGame || ((Killer != None) && (Killer != Killed) && (Killed != None)
								&& (Killer.PlayerReplicationInfo != None) && (Killed.PlayerReplicationInfo != None)
								&& (Killer.PlayerReplicationInfo.Team != Killed.PlayerReplicationInfo.Team)) );
	if ( UnrealPlayer(Killer) != None )
		UnrealPlayer(Killer).LogMultiKills(ADR_MajorKill, bEnemyKill);

	if ( (UnrealPawn(KilledPawn) != None) && (UnrealPawn(KilledPawn).Spree > 4) )
	{
		if ( bEnemyKill && (Killer != None) )
			Killer.AwardAdrenaline(ADR_MajorKill);
		EndSpree(Killer, Killed);
	}
	if ( (Killer != None) && Killer.bIsPlayer && (Killed != None) && Killed.bIsPlayer )
	{
		DamageType.static.IncrementKills(Killer);

		if ( !bFirstBlood && (Killer != Killed) && bEnemyKill )
		{
			Killer.AwardAdrenaline(ADR_MajorKill);
			bFirstBlood = True;
			if ( TeamPlayerReplicationInfo(Killer.PlayerReplicationInfo) != None )
				TeamPlayerReplicationInfo(Killer.PlayerReplicationInfo).bFirstBlood = true;
			BroadcastLocalizedMessage( class'FirstBloodMessage', 0, Killer.PlayerReplicationInfo );
			SpecialEvent(Killer.PlayerReplicationInfo,"first_blood");
		}
		if ( Killer == Killed )
			Killer.AwardAdrenaline(ADR_MinorError);
		else if ( bTeamGame && (Killed.PlayerReplicationInfo.Team == Killer.PlayerReplicationInfo.Team) )
			Killer.AwardAdrenaline(ADR_KillTeamMate);
		else if ( UnrealPawn(Killer.Pawn) != None )
		{
			Killer.AwardAdrenaline(10);
			UnrealPawn(Killer.Pawn).Spree++;
			if ( UnrealPawn(Killer.Pawn).Spree > 4 )
				NotifySpree(Killer, UnrealPawn(Killer.Pawn).Spree);
		}
	}

    //Killed function of Gameinfo

    if ( (Killed != None) && Killed.bIsPlayer )
    {
        Killed.PlayerReplicationInfo.Deaths += 1;
        BroadcastDeathMessage(Killer, Killed, damageType);

		if ( (Killer == Killed) || (Killer == None) )
		{
			if ( Killer == None )
				KillEvent("K", None, Killed.PlayerReplicationInfo, DamageType);	//"Kill"
			else
				KillEvent("K", Killer.PlayerReplicationInfo, Killed.PlayerReplicationInfo, DamageType);	//"Kill"
		}
		else
		{
			if ( bTeamGame && (Killer.PlayerReplicationInfo != None)
				&& (Killer.PlayerReplicationInfo.Team == Killed.PlayerReplicationInfo.Team) )
				KillEvent("TK", Killer.PlayerReplicationInfo, Killed.PlayerReplicationInfo, DamageType);	//"Teamkill"
			else
				KillEvent("K", Killer.PlayerReplicationInfo, Killed.PlayerReplicationInfo, DamageType);	//"Kill"
		}
    }
    if ( Killed!=None && DamageType!=class'TaskForces.DamTypeGuardProjR' && DamageType!=class'TaskForces.DamTypeProtR' && DamageType!=class'TaskForces.DamTypeGuardProjB' && DamageType!=class'TaskForces.DamTypeProtB' )
	    ScoreKill(Killer, Killed);

    DiscardInventory(KilledPawn);
    NotifyKilled(Killer,Killed,KilledPawn);

    //Super.Killed(Killer, Killed, KilledPawn, damageType);
}

function ScoreKill(Controller Killer, Controller Other)
{
	local PlayerReplicationInfo OtherPRI;

	OtherPRI = Other.PlayerReplicationInfo;

    //Autotaunts
	if ( bAllowTaunts && (Killer != None) && (Killer != Other) && Killer.AutoTaunt() && (Killer.PlayerReplicationInfo.VoiceType != None) )
	{
		if( Killer.IsA('PlayerController') )
			Killer.SendMessage(OtherPRI, 'AUTOTAUNT', Killer.PlayerReplicationInfo.VoiceType.static.PickRandomTauntFor(Killer, false, false), 10, 'GLOBAL');
		else
			Killer.SendMessage(OtherPRI, 'AUTOTAUNT', Killer.PlayerReplicationInfo.VoiceType.static.PickRandomTauntFor(Killer, false, true), 10, 'GLOBAL');
	}

    //score
    if( (killer == Other) || (killer == None) )
	{
    	if (Other!=None)
        {
    	    tfpri(other.PlayerReplicationInfo).SubSkill(-50);
		    tfpri(other.PlayerReplicationInfo).SubRes(-BountyAmount*2);
            Other.PlayerReplicationInfo.Score -= 2;
		    ScoreEvent(Other.PlayerReplicationInfo,-2,"self_frag");
	    }
    }
    else if ( killer.PlayerReplicationInfo != None )
	{
		Killer.PlayerReplicationInfo.Kills++;

        //teamkill
        if(Killer.PlayerReplicationInfo.Team == Other.PlayerReplicationInfo.Team)
        {
            Killer.PlayerReplicationInfo.Score-=1;
            tfpri(killer.PlayerReplicationInfo).SubSkill(-25);
            tfpri(killer.PlayerReplicationInfo).SubRes(-BountyAmount);
            ScoreEvent(Killer.PlayerReplicationInfo, -1,"team_frag");
		}
		else //normal kill
		{
            Killer.PlayerReplicationInfo.Score+=1;
		    tfpri(killer.PlayerReplicationInfo).AddSkill(SkillAmount);
		    tfpri(killer.PlayerReplicationInfo).AddRes(BountyAmount);
            ScoreEvent(Killer.PlayerReplicationInfo,1,"frag");
        }
	}

    if ( GameRulesModifiers != none )
        GameRulesModifiers.ScoreKill(Killer, Other);
}

event PlayerController Login( string Portal, string Options, out string Error )
{
	local PlayerController pc;

	pc = Super.Login(Portal, Options, Error);

	if(pc != None)
	{
        pc.PawnClass = class'TaskForces.TFPawn';
	}

	return pc;
}

//link teaminfos and give startRES
function StartMatch()
{
    local teaminfo t;
    local tfgri gri;

    super.StartMatch();

    foreach allactors( class'teaminfo', t)
	{
	    if(tfgri(gamereplicationinfo).team[t.teamindex]==none)
                tfgri(gamereplicationinfo).team[t.teamindex]=t;
    }

    gri=tfgri(gamereplicationinfo);

    gri.AddTeamRes(startupResources, 0, true);
    gri.AddTeamRes(startupResources, 1, true);

    gri.MaxControl[0]=BuildLimit;
    gri.MaxControl[1]=BuildLimit;
}

function CheckScore(PlayerReplicationInfo Scorer)
{
	if ( CheckMaxLives(Scorer) )
		return;

    if ( (GameRulesModifiers != None) && GameRulesModifiers.CheckScore(Scorer) )
		return;

    if (  !bOverTime && (GoalScore == 0) )
		return;

    if ( (Scorer != None) && (Scorer.Team != None) && (Scorer.Team.Score >= GoalScore) )
		EndGame(Scorer,"teamscorelimit");

    if ( (Scorer != None) && bOverTime )
		EndGame(Scorer,"timelimit");
}

static function PrecacheGameTextures(LevelInfo myLevel)
{
	myLevel.AddPrecacheMaterial(Texture'SmokeAlphab_t');
    myLevel.AddPrecacheMaterial(Texture'TFmedia.Nukeflash');

    class'xTeamGame'.static.PrecacheGameTextures(myLevel);
}

static function PrecacheGameStaticMeshes(LevelInfo myLevel)
{
    myLevel.AddPrecacheStaticMesh(StaticMesh'TFMedia.TFShockwave');
    myLevel.AddPrecacheStaticMesh(StaticMesh'TFMedia.TFthinring');
    myLevel.AddPrecacheStaticMesh(StaticMesh'TFMedia.TFShroom');

    class'xDeathMatch'.static.PrecacheGameStaticMeshes(myLevel);
}

defaultproperties
{
     SIGPropsDisplayText(0)="Bounty Amount"
     SIGPropsDisplayText(1)="Outpost Distance"
     SIGPropsDisplayText(2)="Startup Resources"
     SIGPropsDisplayText(3)="Control Capacity"
     SIGPropsDisplayText(4)="Outpost Area Size"
     SIGPropsDisplayText(5)="Generator Rate"
     SIGPropsDisplayText(6)="Construction Areas"
     SIGPropsDisplayText(7)="Minimum Income"
     SIGPropsDisplayText(8)="Skill Amount"
     SIGPropsDisplayText(9)="Enable Warheads"
     SIGPropsDisplayText(10)="Enable Fast Building"
     SIGPropsDisplayText(11)="Territories"
     SIGPropsDisplayText(12)="Max Sentinels"
     SIGPropsDisplayText(13)="Allow Upgrades"
     SIGPropsDisplayText(14)="Unlimited Resouces"
     SIGPropDescText(0)="You will gain this much Energy for killing an enemy."
     SIGPropDescText(1)="The minimum distance one Outpost need to another (measured in meters). Adjust this value according to the size of the map."
     SIGPropDescText(2)="Every player will start the match with this much Energy."
     SIGPropDescText(3)="Your team can spend up to this much Energy for construction. Ouposts increase the maximum."
     SIGPropDescText(4)="Radius of Outpost area will be this much percent of Outpost Distance."
     SIGPropDescText(5)="A standard Generator produces this much Energy per minute."
     SIGPropDescText(6)="When activated, construction is only allowed near Outposts and the BaseCore. The Radius is equal to the Outpost Distance."
     SIGPropDescText(7)="The BaseCore produces this amount of Energy per minute."
     SIGPropDescText(8)="You will gain this much Skill Points for killing an enemy."
     SIGPropDescText(9)="Allows you to turn Warheads on or off."
     SIGPropDescText(10)="Increases building speed for testing purposes."
     SIGPropDescText(11)="When activated, construction is not allowed in enemy territories, structures may still be placed inside your own territory or in no mans land."
     SIGPropDescText(12)="Set the maximum number of deployer Sentinels per person. Leave at 0 for unlimited."
     SIGPropDescText(13)="Allows you to turn Sentinel Upgrades on or off."
     SIGPropDescText(14)="Provides Infinite Resources for testing purposes."
     DefWeapons(0)=Class'taskforces.TFAssaultRifle'
     DefWeapons(1)=class'Taskforces.TFShieldGun'
     DefWeapons(2)=Class'taskforces.TFConstructor'
     DefWeapons(3)=Class'taskforces.TFWLGun'
     bScoreTeamKills=False
     bSpawnInTeamArea=True
     bScoreVictimsTarget=True
     TeamAIType(0)=class'UnrealGame.TeamAI'
     TeamAIType(1)=class'UnrealGame.TeamAI'
     ADR_Kill=2.000000
     HUDType="Taskforces.TFHUD"
     MapListType="XInterface.MapListSiege"
     MapPrefix="CTF"
     MapPrefixtwo="BR"
     BeaconName="SIG"
     GoalScore=3
     TimeLimit=15
     OtherMesgGroup="CTFGame"
     MutatorClass="TaskForces.TFMainMut"
     GameName="Siege"
     ScreenShotName="TFMedia.SiegeSequence"
     DecoTextName="XGame.CTFGame"
     Acronym="SIG"
}
